#ifndef DW_MATHS_UTILS_H
#	define DW_MATHS_UTILS_H

namespace dw {
	namespace maths {

static const float32 pi = 3.141592653589793238462643383279502884197f;
static const float32 sqrPi = 3.141592653589793238462643383279502884197f * 3.141592653589793238462643383279502884197f;

static const float32 two_pi_3 = 2.0943951023931954923084f;
static const float32 two_pi_43 = 4.1887902047863909846168f;

static const double e  = 2.718281828459045235360287471352662497757;

template< typename T >
inline static T square(const T& x);

template< typename T >
inline static T lerp(const T& a, const T& b, const float& t);

inline unsigned gcd(unsigned a, unsigned b);

inline unsigned lcm(unsigned a, unsigned b);

template< typename T >
inline T square(const T& x)
{
	return (x * x);
}

inline unsigned gcd(unsigned a, unsigned b)
{
	unsigned g = 1;
	unsigned t = 0;

	while ((a % 2 == 0) && (b % 2 == 0))
	{  
		a /= 2;
		b /= 2;
		g *= 2;
	}
	while (a > 0)
	{
		if (a % 2 == 0)
			a /= 2;
		else 
			if (b % 2 == 0)
				b /= 2;
			else
			{  
				t = std::abs((int)a - (int)b) / 2;
				if (a < b)
					b = t;
				else
					a = t;
			}
	}  
	return (g * b);
}

inline unsigned lcm(unsigned a, unsigned b)
{
	return (a * b / gcd(a, b));
}

template< typename T >
inline T lerp(const T& a, const T& b, const float& t)
{
	return (a + t * (b - a));
}

template< typename T >
inline T hermite(const T& a, const T& b, const T& at, const T& bt, const float& t)
{
	return 
		(+2 * t * t * t - 3 * t * t + 1	) * a		+ 
		(-2 * t * t * t + 3 * t * t			) * b		+ 
		(+1 * t * t * t - 2 * t * t + t	) * at	+ 
		(+1 * t * t * t - 1 * t * t			) * bt;
}

template< typename T > 
inline T bezier(const T& a, const T& b, const T& ac, const T& bc, const float& t)
{
	return
		(-1 * s * s * s + 3 * s * s - 3 * s + 1	) * a		+
		(+3 * s * s * s - 6 * s * s + 3 * s			) * b		+
		(-3 * s * s * s + 3 * s * s							) * ac	+
		(+1 * s * s * s													) * bc;
}

	} // namespace maths
} // namespace dw

#endif // !DW_MATHS_UTILS_H
